package com.eastdigit.org.service;

import com.eastdigit.org.inter.DepartmentMapper;
import com.eastdigit.org.model.Department;
import com.eastdigit.system.model.BusinessException;
import com.eastdigit.system.model.Constants;
import com.eastdigit.system.service.BaseTreeService;
import com.eastdigit.system.service.IDataScopeService;
import com.eastdigit.system.service.IDepartmentService;
import com.eastdigit.system.service.IRoleService;
import com.eastdigit.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class DepartmentService extends BaseTreeService implements IDepartmentService {

    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private CacheManager cacheManager;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IDataScopeService dataScopeService;

    /**
     * 获取所有的部门
     * 
     * @return
     */
    @Override
    // @Cacheable(value = "_departmentCache", key = "'all'")
    public List<Department> queryAllDepartment() {
        // 这里手动缓存，不然在当前方法内调用缓存无效
        Cache cache = cacheManager.getCache("_departmentCache");
        Object value = cache.get("all");
        if (value instanceof SimpleValueWrapper) {// 存在缓存
            return (List<Department>) ((SimpleValueWrapper) value).get();
        } else {
            List<Department> list = departmentMapper.selectAllDepartment();
            cache.put("all", list);
            return list;
        }
    }

    @Override
    @Cacheable(value = "_departmentCache", key = "#deptId")
    public Department queryDepartment(String deptId) {
        return departmentMapper.selectByPrimaryKey(deptId);
    }

    /**
     * 通过deptId查找所有祖先，按照祖先的层级排序
     * 
     * @param deptId
     * @return
     */
    @Override
    @Cacheable(value = "_departmentCache", key = "'ac_' + #deptId")
    public List<Department> queryAncestorDepartment(String deptId) {
        Map<String, Department> map = new HashMap<String, Department>();
        List<Department> depts = queryAllDepartment();
        for (Department dept : depts) {
            map.put(dept.getDeptId(), dept);
        }
        List<Department> list = new ArrayList<Department>();

        addParent(map, list, deptId);
        return list;
    }

    /**
     * 递归添加上级
     * 
     * @param map
     * @param list
     * @param deptId
     */
    private void addParent(Map<String, Department> map, List<Department> list, String deptId) {
        Department dept = map.get(deptId);
        if (dept != null) {
            Department parent = map.get(dept.getParentId());
            if (parent != null) {
                list.add(0, parent);
                this.addParent(map, list, parent.getDeptId());
            }
        }
    }

    @Override
    @Cacheable(value = "_departmentCache", key = "'ds_' + #parentDeptId")
    public List<Department> queryDescendantDepartmentAndSelf(String parentDeptId) {
        List<Department> list = new ArrayList<Department>();
        if (StringUtils.isBlank(parentDeptId) || "0".equals(parentDeptId)) {
            list.addAll(queryAllDepartment());
        } else {
            Department parent = queryDepartment(parentDeptId);
            if (parent != null) {
                list.add(parent);
                // list.addAll(queryChildrenDepartment(parentDeptId));
                queryChildrenDepartmentRecursion(list, parent.getId());
            }
        }
        return list;
    }

    @Override
    @Cacheable(value = "_departmentCache", key = "'d_' + #parentDeptId")
    public List<Department> queryDescendantDepartment(String parentDeptId) {
        List<Department> list = new ArrayList<Department>();
        queryChildrenDepartmentRecursion(list, parentDeptId);
        return list;
    }

    /**
     * 递归查询子节点
     * 
     * @param list
     * @param parentDeptId
     */
    private void queryChildrenDepartmentRecursion(List<Department> list, String parentDeptId) {
        for (Department department : queryChildDepartment(parentDeptId)) {
            list.add(department);
            queryChildrenDepartmentRecursion(list, department.getId());
        }
    }

    /**
     * 获取某部门的子节点
     * 
     * @param parentDeptId
     * @return
     */
    @Override
    @Cacheable(value = "_departmentCache", key = "'c_' + #parentDeptId")
    public List<Department> queryChildDepartment(String parentDeptId) {
        // return departmentMapper.selectByParentId(parentDeptId);
        List<Department> list = new ArrayList<Department>();
        for (Department department : queryAllDepartment()) {
            if (department.getParentId().equals(parentDeptId)) {
                list.add(department);
            }
        }
        return list;
    }

    /**
     * 增加部门
     * 
     * @param department
     */
    @CacheEvict(value = "_departmentCache", allEntries = true)
    public void addDepartment(Department department) {
        // Department department = getDepartment(reqBean);
        department.setId(intIncrementId("SYS_DEPARTMENT", "DEPT_ID"));
        department.setMakeTime(new Date());
        department.setModifyTime(department.getMakeTime());
        resetFullNameAndInnerId(department, null);

        departmentMapper.insert(department);

        // 更新数据范围表
        dataScopeService.updateByDeptAdd(department.getDeptId(), department.getParentDeptId());
    }

    /**
     * 更新部门
     * 
     * @param department
     */
    @CacheEvict(value = "_departmentCache", allEntries = true)
    public void updateDepartment(Department department) {
        String deptId = department.getId();
        if (StringUtil.isEmpty(deptId)) {
            throw new BusinessException("获取主键失败");
        }
        department.setModifyTime(new Date());

        String parentId = department.getParentId();
        Department tmp = departmentMapper.selectByPrimaryKey(deptId);
        if (tmp == null) {
            throw new BusinessException("获取部门失败");
        }
        if (!tmp.getParentDeptId().equals(parentId)) {// 部门层级改变了
            List<Department> list = queryDescendantDepartment(deptId);

            if (deptId.equals(parentId)) {
                throw new BusinessException("上级机构不能设置为其本身！");
            }
            for (Department dept : list) {
                if (dept.getId().equals(parentId)) {
                    throw new BusinessException("上级机构不能设置为其下级机构！");
                }
            }

            resetFullNameAndInnerId(department, null);
        }

        departmentMapper.updateByPrimaryKeySelective(department);

        if (!tmp.getParentDeptId().equals(parentId)) {// 部门层级改变了
            // 更新数据范围表
            dataScopeService.updateByDeptUpdate(department.getDeptId(), department.getParentDeptId());
        }
    }

    /**
     * 删除部门
     * 
     * @param deptId
     */
    @CacheEvict(value = "_departmentCache", allEntries = true)
    public void deleteDepartment(String deptId) {
        // String deptId = reqBean.getInfo("deptId");
        if (StringUtil.isEmpty(deptId)) {
            throw new BusinessException("获取主键失败");
        }

        Department department = queryDepartment(deptId);
        if (department == null) {
            throw new BusinessException("部门不存在");
        }
        if (Constants.DEPT_ROOT_PARENT_ID.equals(department.getParentId())) {
            throw new BusinessException("该公司不允许删除！");
        }

        if (queryChildDepartment(deptId).size() > 0) {
            throw new BusinessException("请先删除下级部门！");
        }

        // 删除部门下的角色
        roleService.deleteByDeptId(deptId);
        // 更新数据范围表
        dataScopeService.updateByDeptDelete(deptId);

        departmentMapper.deleteByPrimaryKey(deptId);
    }

    /**
     * 修改全称和内部编码
     * 
     * @param department
     * @param parent
     */
    private void resetFullNameAndInnerId(Department department, Department parent) {
        if (parent == null) {
            parent = departmentMapper.selectByPrimaryKey(department.getParentId());
        }
        if (parent != null) {// 存在上级
            department.setFullName(parent.getFullName() + "/" + department.getShortName());
            department.setInnerId(parent.getInnerId() + "/" + department.getId());
        } else {// 没有上级
            department.setFullName(department.getShortName());
            department.setInnerId(department.getId());
        }
        resetChildFullNameAndInnerId(department);
    }

    /**
     * 修改子类全称和内部编码
     * 
     * @param parent
     */
    private void resetChildFullNameAndInnerId(Department parent) {
        List<Department> list = queryChildDepartment(parent.getId());
        for (Department department : list) {
            resetFullNameAndInnerId(department, parent);
            departmentMapper.updateByPrimaryKey(department);
            resetChildFullNameAndInnerId(department);
        }
    }

}
